package cn.sdormitory.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.sdormitory.attendance.dao.HolidayConfigDao;
import cn.sdormitory.attendance.entity.HolidayConfig;
import cn.sdormitory.basedata.dao.BClassDao;
import cn.sdormitory.basedata.dao.BStudentDao;
import cn.sdormitory.basedata.dto.StudentDept;
import cn.sdormitory.basedata.entity.BClass;
import cn.sdormitory.basedata.entity.BStudent;
import cn.sdormitory.basedata.vo.BClassVo;
import cn.sdormitory.common.sms.TxSmsTemplate;
import cn.sdormitory.dormitoryHygiene.dao.DormitoryHygieneDao;
import cn.sdormitory.leavingSchool.dao.LeavingSchoolCertificateDao;
import cn.sdormitory.leavingSchool.entity.LeavingSchoolCertificate;
import cn.sdormitory.mq.LeaveMessageSender;
import cn.sdormitory.service.AppSyssetSmsTemplateService;
import cn.sdormitory.smartdor.dao.SdWeekendAttenceDao;
import cn.sdormitory.smartdor.entity.SdWeekendAttence;
import cn.sdormitory.sys.dao.SysConfigDao;
import cn.sdormitory.sys.dao.SysDictDetailDao;
import cn.sdormitory.sys.dao.SysUserDao;
import cn.sdormitory.sys.entity.SysConfig;
import cn.sdormitory.sys.entity.SysDictDetail;
import cn.sdormitory.sys.entity.SysUser;
import cn.sdormitory.utils.wx.WeChatMessageSendUtil;
import cn.sdormitory.workflow.dao.StuLeaveApplyDao;
import cn.sdormitory.workflow.entity.StuLeaveApply;
import cn.sdormitory.basedata.service.BStudentService;
import cn.sdormitory.basedata.vo.BClassStudentVo;
import cn.sdormitory.common.constant.CommonConstant;
import cn.sdormitory.service.AppSdStudentLeaveService;
import cn.sdormitory.smartdor.dao.SdLeaveDao;
import cn.sdormitory.smartdor.dao.SdStudentLeaveDao;
import cn.sdormitory.smartdor.entity.SdAttence;
import cn.sdormitory.smartdor.entity.SdLeave;
import cn.sdormitory.smartdor.service.SdAttenceService;
import cn.sdormitory.smartdor.vo.SdStudentLeaveVo;
import cn.sdormitory.wx.entity.WxPushInfo;
import cn.sdormitory.wx.service.WxPushInfoService;
import cn.sdormitory.wx.utils.WXUtil;
import cn.sdormitory.wx.utils.WeatherDataCreator;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * @创建人：zhouyang
 * @创建时间：2021/11/15 22:28
 * @version：V1.0
 */
@Service
@Slf4j
public class AppSdStudentLeaveServiceImpl extends ServiceImpl<SdStudentLeaveDao, SdStudentLeaveVo> implements AppSdStudentLeaveService {
    @Resource
    private SdStudentLeaveDao sdStudentLeaveDao;
    @Resource
    private SdLeaveDao sdLeaveDao;
    @Resource
    private BStudentService bStudentService;
    @Resource
    private SdAttenceService sdAttenceService;
    
    @Resource
    private SdWeekendAttenceDao sdWeekendAttenceDao;
    
    @Resource
    private LeaveMessageSender leaveMessageSender;
    
    @Autowired
    private StuLeaveApplyDao stuLeaveApplyDao;
    @Autowired
    private BClassDao bClassDao;
    @Autowired
    private BStudentDao bStudentDao;

    @Resource
    private SysConfigDao sysConfigDao;

    @Autowired
    WeChatMessageSendUtil weChatMessageSendUtil;

    @Autowired
    WeatherDataCreator weatherDataCreator;

    @Autowired
    WxPushInfoService wxPushInfoService;

    @Resource
    private DormitoryHygieneDao dormitoryHygieneDao;

    @Resource
    private LeavingSchoolCertificateDao schoolCertificateDao;

    @Autowired
    WXUtil wxUtil;

    @Value("${wxsmall.studentLeave_temp_id}")
    private String studentLeave_temp_id;

    @Value("${wxsmall.leaveResult_temp_id}")
    private String leaveResult_temp_id;

    @Resource
    SysUserDao sysUserDao;

    @Resource
    SysDictDetailDao sysDictDetailDao;

    @Autowired
    private TxSmsTemplate txSmsTemplate;
    
    @Autowired
    private TaskExecutor taskExecutor;

    @Resource
    private HolidayConfigDao holidayConfigDao;

    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");

    @Resource
    private AppSyssetSmsTemplateService appSyssetSmsTemplateService;

    @Override
    public int create(SdLeave sdLeave) {
        return sdLeaveDao.insert(sdLeave);
    }

    @Override
    public int update(SdLeave sdLeave) {
        sdLeave.setModifyTime(new Date());
        return sdLeaveDao.updateById(sdLeave);
    }

    @Override
    public List<BClassStudentVo> getLeaveByClaNameAndStuName(String className, String studentName) {
        return sdStudentLeaveDao.getLeaveByClaNameAndStuName(className,studentName);
    }

    @Override
    public int deleteStuLeave(Long leaveId, String studentNo, String startDate, String endDate) {
        //查询请假信息
        BClassStudentVo info = sdStudentLeaveDao.getStudentLeavenDetail(leaveId);
        //获取当前日期
        String nowDate = DateUtil.today();
        String yesterday = DateUtil.format(DateUtil.yesterday(),"YYYY-MM-dd");
        //开始日期为当前日期，则判定可以全部删除
        if(nowDate.equals(startDate)){
            sdStudentLeaveDao.deleteStuLeave(leaveId);
        }else{
            sdStudentLeaveDao.updateStudentLeave(leaveId,startDate,yesterday);
            startDate = nowDate;
        }
        int count1=sdStudentLeaveDao.deleteByLeaAndAtt(studentNo,startDate,endDate);
        return count1;
    }

    @Override
    public List<SdStudentLeaveVo> getStuLeaveByDateAndStuNo(String studentNo, String startDate, String endDate) {
        return sdStudentLeaveDao.getStuLeaveByDateAndStuNo(studentNo,startDate,endDate);
    }

    @Override
    public int addStudentLeave(SdStudentLeaveVo sdStudentLeaveVo) {
        int count = 0;
        try {
            String[] studentNoArray = sdStudentLeaveVo.getStudentNoArray();
            String[] studentNameArray= sdStudentLeaveVo.getStudentNameArray();
            String[] phoneArray=sdStudentLeaveVo.getPhoneArray();
            Long[] leaveDays=sdStudentLeaveVo.getLeaveDays();
            String[] startDateArray=sdStudentLeaveVo.getStartDateArray();
            String[] endDateArray=sdStudentLeaveVo.getEndDateArray();
            Long[] leaveId=sdStudentLeaveVo.getLeaveId();
            String[] leaveReasonArray = sdStudentLeaveVo.getLeaveReasonArray();
            String[] leaveTypeArray = sdStudentLeaveVo.getLeaveTypeArray();

            if(leaveDays!=null && leaveDays.length>0) {
                for (int i = 0; i < leaveDays.length; i++) {
                    //如果请假天数大余0且请假ID为空或0则为新增
                    if(leaveDays[i]>0 && (leaveId[i]==null || leaveId[i]==0)){
                        //根据学号以及请假时间查询请假记录是否已存在
                        SdLeave sdLeave1=sdLeaveDao.getLeaveByStuNoAndLeaDate(studentNoArray[i],startDateArray[i],endDateArray[i]);
                        if(sdLeave1!=null){//新增请假时间有重复
                            return -1;
                        }
                            SdLeave sdLeave = new SdLeave();
                            sdLeave.setClassId(sdStudentLeaveVo.getClassId());
                            sdLeave.setClassName(sdStudentLeaveVo.getClassName());
                            sdLeave.setStatus("3");
                            sdLeave.setStudentNo(studentNoArray[i]);
                            sdLeave.setStudentName(studentNameArray[i]);
                            sdLeave.setStartDate(startDateArray[i]);
                            sdLeave.setEndDate(endDateArray[i]);
                            sdLeave.setStudentPhone(phoneArray[i]);
                            sdLeave.setLeaveReason(leaveReasonArray[i]);
                            sdLeave.setLeaveType(leaveTypeArray[i]);
                            int insertCount=sdLeaveDao.insert(sdLeave);
                            if(insertCount>0){
                                BStudent bStudent=bStudentService.getByStudentNo(studentNoArray[i]);
                                //向考勤表添加考勤信息
                                SdAttence sdAttence = new SdAttence();
                                sdAttence.setAccessDate(new Date());
                                sdAttence.setStudentNo(studentNoArray[i]);
                                sdAttence.setAttenceStatus(CommonConstant.ATTENDANCE_LEAVE);
                                sdAttence.setBdormitoryId(bStudent.getBdormitoryId());
                                sdAttence.setBuildingNo(bStudent.getBuildingNo());
                                sdAttence.setStorey(bStudent.getStorey());
                                sdAttence.setDormitoryNo(bStudent.getDormitoryNo());
                                sdAttence.setFlag("3");
                                sdAttence.setCreateTime(new Date());
                                sdAttence.setModifyTime(new Date());
                                //2021-11-1需求变更（支持一次性请假多天）
                                try {
                                    Calendar calendar=new GregorianCalendar();
                                    calendar.setTime(sdf.parse(startDateArray[i]));
                                    Calendar endCalendar=new GregorianCalendar();
                                    endCalendar.setTime(sdf.parse(endDateArray[i]));
                                    // 如果开始、结束日期相同，则while循环次数为0
                                    while (calendar.before(endCalendar)){
                                        sdAttence.setAccessDate(calendar.getTime());
                                        sdAttenceService.insert(sdAttence);
                                        calendar.add(Calendar.DATE,1);
                                    }
                                    sdAttence.setAccessDate(sdf.parse(endDateArray[i]));
                                    sdAttenceService.insert(sdAttence);
                                } catch (ParseException e) {
                                    e.printStackTrace();
                                }
                                
                                // 向周末考勤表中添加考勤信息
                                SdWeekendAttence sdWeekendAttence = new SdWeekendAttence();
                                sdWeekendAttence.setAccessDate(new Date());
                                sdWeekendAttence.setStudentNo(studentNoArray[i]);
                                sdWeekendAttence.setAttenceStatus(CommonConstant.ATTENDANCE_LEAVE);
                                sdWeekendAttence.setBdormitoryId(bStudent.getBdormitoryId());
                                sdWeekendAttence.setBuildingNo(bStudent.getBuildingNo());
                                sdWeekendAttence.setStorey(bStudent.getStorey());
                                sdWeekendAttence.setDormitoryNo(bStudent.getDormitoryNo());
                                sdWeekendAttence.setFlag("3");
                                sdWeekendAttence.setCreateTime(new Date());
                                sdWeekendAttence.setModifyTime(new Date());
                                //2021-11-1需求变更（支持一次性请假多天）
                                try {
                                    Calendar calendar=new GregorianCalendar();
                                    calendar.setTime(sdf.parse(startDateArray[i]));
                                    Calendar endCalendar=new GregorianCalendar();
                                    endCalendar.setTime(sdf.parse(endDateArray[i]));
                                    // 如果开始、结束日期相同，则while循环次数为0
                                    while (calendar.before(endCalendar)){
                                        sdWeekendAttence.setAccessDate(calendar.getTime());
                                        sdWeekendAttenceDao.insert(sdWeekendAttence);
                                        calendar.add(Calendar.DATE,1);
                                    }
                                    sdWeekendAttence.setAccessDate(sdf.parse(endDateArray[i]));
                                    sdWeekendAttenceDao.insert(sdWeekendAttence);
                                } catch (ParseException e) {
                                    e.printStackTrace();
                                }
                             }
                    }

                    if(leaveId[i]!=null && leaveId[i]>0){
                        //当前日期等于开始日期的记录
                        int result1=sdStudentLeaveDao.getStuLeaveCount(leaveId[i]);
                        //当前日期在开始时间或结束时间在已存在的记录中的任意一天则把之前的记录更新为开始时间不变，结束时间为当前日期的前一天
                        int result2=sdStudentLeaveDao.getStuLeaveCountById(leaveId[i],startDateArray[i],endDateArray[i]);
                         if(leaveDays[i]>0) {
                             sdStudentLeaveDao.updateStudentEndLeave(leaveId[i], endDateArray[i]);
                             //根据学号+请假日期查询考勤表中对应的所有数据先删除今天前的所有数据再新增考勤表数据
                             sdStudentLeaveDao.deleteByStuNo(studentNoArray[i]);
                             try {
                                 BStudent bStudent = bStudentService.getByStudentNo(studentNoArray[i]);
                                 SdAttence sdAttence = new SdAttence();
                                 sdAttence.setAccessDate(new Date());
                                 sdAttence.setStudentNo(studentNoArray[i]);
                                 sdAttence.setAttenceStatus(CommonConstant.ATTENDANCE_LEAVE);
                                 sdAttence.setBdormitoryId(bStudent.getBdormitoryId());
                                 sdAttence.setBuildingNo(bStudent.getBuildingNo());
                                 sdAttence.setStorey(bStudent.getStorey());
                                 sdAttence.setDormitoryNo(bStudent.getDormitoryNo());
                                 sdAttence.setFlag("3");
                                 sdAttence.setCreateTime(new Date());
                                 sdAttence.setModifyTime(new Date());
                                 //2021-11-1需求变更（支持一次性请假多天）
                                     Calendar calendar = new GregorianCalendar();
                                     calendar.setTime(sdf.parse(startDateArray[i]));
                                     Calendar endCalendar = new GregorianCalendar();
                                     endCalendar.setTime(sdf.parse(endDateArray[i]));
                                     // 如果开始、结束日期相同，则while循环次数为0
                                     while (calendar.before(endCalendar)) {
                                         sdAttence.setAccessDate(calendar.getTime());
                                         sdAttenceService.insert(sdAttence);
                                         calendar.add(Calendar.DATE, 1);
                                     }
                                     sdAttence.setAccessDate(sdf.parse(endDateArray[i]));
                                     sdAttenceService.insert(sdAttence);
                                 } catch (ParseException e) {
                                     e.printStackTrace();
                                 }

                         }
                         if(leaveDays[i]==0 && result1>0){
                             sdStudentLeaveDao.deleteStuLeave(leaveId[i]);
//                             Calendar calendar=new GregorianCalendar();
//                             calendar.setTime(sdf.parse(startDateArray[i]));
//                             Calendar endCalendar=new GregorianCalendar();
//                             endCalendar.setTime(sdf.parse(endDateArray[i]));
//                             // 如果开始、结束日期相同，则while循环次数为0
//                             while (calendar.before(endCalendar)){
//                                 calendar.add(Calendar.DATE,1);
//                                 sdAttenceService.deleteByStuNoAndADate(studentNoArray[i],sdf.format(calendar.getTime()));
//                             }
//                             sdAttenceService.deleteByStuNoAndADate(studentNoArray[i],sdf.format(calendar.getTime()));
                             //删除考勤表中大余等于今天的数据
                             sdStudentLeaveDao.deleteByStuNo(studentNoArray[i]);
                         }
                         if(leaveDays[i]==0 && result2>0){
                             SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
                            // Date date1=sdf.parse(endDateArray[i]);
                             Calendar c = Calendar.getInstance();
                             c.setTime(new Date());
                             int day=c.get(Calendar.DATE);
                             c.set(Calendar.DATE,day-1);
                             String dayBefore=sdf.format(c.getTime());
                             sdStudentLeaveDao.updateStudentLeaveEnd(leaveId[i],dayBefore);
                             //删除当前学生大余等于今天的所有考勤数据
                             sdStudentLeaveDao.deleteByStuNo(studentNoArray[i]);
                         }
                    }
                }
            }
            count = 1;
        }catch (Exception ex){
            ex.printStackTrace();
            count = 0;
        }

        return  count;
    }

    /**
     * 查询提交人所提交的请假信息
     * @param sdLeave
     * @return
     */
    @Override
    public List<SdLeave> getStuLeavesList(SdLeave sdLeave) {
        return sdStudentLeaveDao.getStuLeavesList(sdLeave);
    }

    /**
     * 修改请假信息
     * @param sdLeave
     * @return
     */
    @Override
    public int updateStuLeaves(SdLeave sdLeave) {
        //查询请假信息
        List<SdLeave> list = sdStudentLeaveDao.getStuLeavesList(sdLeave);
        int count =0;
        if(null != list && !list.isEmpty()){
            SdLeave vo = list.get(0);
            //删除学生在今天之后包括今天的请假考情记录
            String nowDate = DateUtil.today();
            sdStudentLeaveDao.deleteByStuNoTime(vo.getStudentNo(),nowDate,vo.getEndDate());
            int insertCount = sdStudentLeaveDao.updateStuLeaves(sdLeave);
            if(insertCount>0){
                BStudent bStudent=bStudentService.getByStudentNo(vo.getStudentNo());
                try {
                    //向考勤表添加考勤信息
                    SdAttence sdAttence = new SdAttence();
                    sdAttence.setAccessDate(sdf.parse(sdLeave.getStartDate()));
                    sdAttence.setStudentNo(bStudent.getStudentNo());
                    sdAttence.setAttenceStatus(CommonConstant.ATTENDANCE_LEAVE);
                    sdAttence.setBdormitoryId(bStudent.getBdormitoryId());
                    sdAttence.setBuildingNo(bStudent.getBuildingNo());
                    sdAttence.setStorey(bStudent.getStorey());
                    sdAttence.setDormitoryNo(bStudent.getDormitoryNo());
                    sdAttence.setFlag("3");
                    sdAttence.setCreateTime(new Date());
                    sdAttence.setModifyTime(new Date());
                    //2021-11-1需求变更（支持一次性请假多天）
                    Calendar calendar=new GregorianCalendar();
                    calendar.setTime(sdf.parse(sdLeave.getStartDate()));
                    Calendar endCalendar=new GregorianCalendar();
                    endCalendar.setTime(sdf.parse(sdLeave.getEndDate()));
                    // 如果开始、结束日期相同，则while循环次数为0
                    while (calendar.before(endCalendar)){
                        sdAttence.setAccessDate(calendar.getTime());
                        sdAttenceService.insert(sdAttence);
                        calendar.add(Calendar.DATE,1);
                    }
                    sdAttence.setAccessDate(sdf.parse(sdLeave.getEndDate()));
                    sdAttenceService.insert(sdAttence);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                count = 1;
            }
        }
        return count;
    }

    public boolean theDateIsExceed(String applyDate) {
        String now = DateUtil.now();
        DateTime nowDate = DateUtil.parse(now, "yyyy-MM-dd");
        DateTime parse = DateUtil.parse(applyDate, "yyyy-MM-dd");
        int compare = parse.compareTo(nowDate);
        // 当前时间在申请开始时间之后
        if (compare < 0) {
            return false;
            // 当前时间在申请时间之前
        } else if (compare > 0){
            return true;
        } else {
            // 当前时间与申请开始时间在同一天，则要判断当前时间是否超过了考勤时间
            LambdaQueryWrapper<SysConfig> sdWeekendRulesWrapper = new LambdaQueryWrapper<>();
            sdWeekendRulesWrapper.eq(SysConfig::getParamKey,"attendance.dormitory.rules");
            SysConfig sdWeekendRules = sysConfigDao.selectOne(sdWeekendRulesWrapper);
            String[] attendanceWeekendRange = sdWeekendRules.getParamValue().split("-");
            String weekendStartTime = attendanceWeekendRange[0];

//            String weekendStartTime = "17:00";
            Date currentTime = new Date();
            SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");
            String formattedTime = formatter.format(currentTime);

            LocalTime time1 = LocalTime.parse(formattedTime);
            LocalTime time2 = LocalTime.parse(weekendStartTime);

            int compareTo = time1.compareTo(time2);
            if (compareTo < 0) {
                return true;
            } else {
                return false;
            }
        }
    }

    @Override
    public int createLeaveApply(StuLeaveApply leaveApply) {
        // 如果当前请假时间超过晚上考勤开始时间点，则不允许请当天假期
        if (!theDateIsExceed(leaveApply.getStartDate())) {
            return -2;
        }

        // 如果是周六，则需要查看当前的学生寝室卫生是否达标，达标则可以请假，不达标则不可以请假
        if(!hygieneIsQualified(leaveApply)) {
            return -3;
        }

        List<StuLeaveApply> isRepeat = stuLeaveApplyDao.getLeaveApplyByStuIdAndLeaDate(leaveApply.getStudentId(),
                leaveApply.getStartDate(),leaveApply.getEndDate());
        if(isRepeat != null && isRepeat.size() > 0) {//新增请假时间有重复
            return -1;
        }
        BClass bClass = bClassDao.selectById(leaveApply.getClassId());
        leaveApply.setClsTeacherId(bClass.getClassTeacherId());
        leaveApply.setStatus("0");
        int num = this.stuLeaveApplyDao.insert(leaveApply);
        if(num > 0){
            SysUser sysUser = sysUserDao.selectById(bClass.getClassTeacherId());
            if(!StringUtils.isEmpty(sysUser.getWxOpenId())){
                BStudent student = bStudentDao.selectById(leaveApply.getStudentId());

                LambdaQueryWrapper<SysDictDetail> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(SysDictDetail::getDictType,"leave_type")
                        .eq(SysDictDetail::getDictValue,leaveApply.getLeaveType());
                SysDictDetail dict = sysDictDetailDao.selectOne(wrapper);

                Map<String, Object> weatherDataMap = weatherDataCreator.createStudentWeatherDataMap(student.getStudentName(), sysUser.getUsername(),
                        student.getStudentName(), DateUtil.formatDateTime(new Date()));
                try {

                    JSONObject jsonObject = null;

                    //判断班主任openid是否为空，不为空则根据openid推送模板信息
                    if(!org.springframework.util.StringUtils.isEmpty(sysUser.getWxOpenId())){
                        jsonObject = wxUtil.sendInfo(sysUser.getWxOpenId(), studentLeave_temp_id
                                , weatherDataMap,"");
                    }

                        //判断学生家长openid是否为空，不为空则根据openid推送模板信息
                        if(null != student.getParentWxOpenId() &&
                                org.springframework.util.StringUtils.hasText(student.getParentWxOpenId())){
                            jsonObject = wxUtil.sendInfo(student.getParentWxOpenId(), studentLeave_temp_id
                                    , weatherDataMap,"");
                        }

                    WxPushInfo wxPushInfo = null;

                    //标记推送消息是否成功    1：失败    2：成功
                    Long success = 1L;

                    //消息推送成功则添加推送消息记录成功，失败则记录推送信息失败
                    if (jsonObject!=null && "0".equals(jsonObject.get("errcode").toString())) {
                        // 发送短信通知班主任
                        String[] params = {student.getStudentName()};
                        if(sysUser.getPhone() != null){
                            txSmsTemplate.sendMesModel(sysUser.getPhone(), params, 8);
                        }
                        success = 0L;
                    }

                    wxPushInfo = new WxPushInfo(leaveApply.getStudentId(),leaveApply.getLeaveType(),success);

                    //将推送微信模板消息情况添加数据库
                    boolean save = wxPushInfoService.save(wxPushInfo);
                    System.out.println(save);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }

            }
        }
        return num;
    }
    
    @Override
    public int createNewLeaveApply(StuLeaveApply leaveApply) {
        // 1.判断当前学生能不能请假  如果是周六则需先查看宿舍卫生，走读生不需要看宿舍卫生
        //                        如果是平常时间则需要看请假时间是否有重复
        // 如果是周六，则需要查看当前的学生寝室卫生是否达标，达标则可以请假，不达标则不可以请假
        if(!hygieneIsQualified(leaveApply)) {
            // 宿舍卫生不达标
            return -3;
        }
        
        List<StuLeaveApply> isRepeat = stuLeaveApplyDao.getLeaveApplyByStuIdAndLeaveDate(leaveApply.getStudentId(),
                leaveApply.getStartDate(),leaveApply.getEndDate());
        if(isRepeat != null && isRepeat.size() > 0) {
            //新增请假时间有重复
            return -1;
        }
        
        // 2.新增请假申请
        BClass bClass = bClassDao.selectById(leaveApply.getClassId());
        leaveApply.setClsTeacherId(bClass.getClassTeacherId());
        leaveApply.setStatus("0");
        int num = this.stuLeaveApplyDao.insert(leaveApply);
        if(num > 0){
            SysUser sysUser = sysUserDao.selectById(bClass.getClassTeacherId());
            if(!StringUtils.isEmpty(sysUser.getWxOpenId())){
                BStudent student = bStudentDao.selectById(leaveApply.getStudentId());
            
                Map<String, Object> weatherDataMap = weatherDataCreator.createStudentWeatherDataMap(student.getStudentName(), sysUser.getUsername(),
                        student.getStudentName(), DateUtil.formatDateTime(new Date()));
                try {
                
                    JSONObject jsonObject = null;
                    log.info("班主任微信openid :{}", sysUser.getWxOpenId());
                    //判断班主任openid是否为空，不为空则根据openid推送模板信息
                    if(!org.springframework.util.StringUtils.isEmpty(sysUser.getWxOpenId())){
                        jsonObject = wxUtil.sendInfo(sysUser.getWxOpenId(), studentLeave_temp_id
                                , weatherDataMap,"");
                    }
                
                    //判断学生家长openid是否为空，不为空则根据openid推送模板信息
                    if(null != student.getParentWxOpenId() &&
                            org.springframework.util.StringUtils.hasText(student.getParentWxOpenId())){
                        jsonObject = wxUtil.sendInfo(student.getParentWxOpenId(), studentLeave_temp_id
                                , weatherDataMap,"");
                    }
                
                    WxPushInfo wxPushInfo = null;
                
                    //标记推送消息是否成功    1：失败    2：成功
                    Long success = 1L;
                
                    //消息推送成功则添加推送消息记录成功，失败则记录推送信息失败
                    if (jsonObject!=null && "0".equals(jsonObject.get("errcode").toString())) {
                        // 发送短信通知班主任
                        String[] params = {student.getStudentName()};
                        if(sysUser.getPhone() != null){
                            txSmsTemplate.sendMesModel(sysUser.getPhone(), params, 8);
                        }
                        success = 0L;
                    }
                
                    wxPushInfo = new WxPushInfo(leaveApply.getStudentId(),leaveApply.getLeaveType(),success);
                
                    //将推送微信模板消息情况添加数据库
                    boolean save = wxPushInfoService.save(wxPushInfo);
                    System.out.println(save);
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            
            }
        }
        return num;
    }

    // 返回true则执行正常请假流程， 返回false 则是验证卫生不合格
    private boolean hygieneIsQualified(StuLeaveApply leaveApply) {
        // 查询学生信息
        BStudent bStudent = bStudentDao.selectById(leaveApply.getStudentId());

        // 非住宿生不需要考虑宿舍卫生
        if (Objects.isNull(bStudent.getBdormitoryId())) {
            return true;
        }

        // 查询是否是放假前一天
        Date date = new Date();
        String accessDate = DateUtils.formatDate(date, "yyyy-MM-dd");
        List<HolidayConfig> holiday = holidayConfigDao.getHolidayByDate(accessDate);

        // 查询该生是哪个部门
        BClass bClass = bClassDao.selectById(leaveApply.getClassId());

        String deptId = String.valueOf(Integer.parseInt(bClass.getClassDept()) + 4);
        // 判断是否有配置假期
        if (holiday.stream().noneMatch(holidayConfig -> deptId.equals(String.valueOf(holidayConfig.getDeptId())))) {
            // 没有假期配置，则直接返回，不需要判断卫生是否合格
            return true;
        }

        boolean needCheckHygiene = false;
        // 有假期配置，则需要判断当前时间是否在放假当天
        for (HolidayConfig holidayConfig : holiday) {
            if (holidayConfig.getHolidayStart().equals(accessDate) && deptId.equals(String.valueOf(holidayConfig.getDeptId()))) {
                needCheckHygiene = true;
            }
        }

        // 不在当前放假时间，不需要判断卫生
        if (!needCheckHygiene) {
            return true;
        }

        // 如果是放假前一天，则需要判断查询卫生是否合格 根据该生的宿舍id查询
        String hygieneGrade = dormitoryHygieneDao.getHygieneGrade(accessDate, String.valueOf(bStudent.getBdormitoryId()));
        if (Objects.isNull(hygieneGrade) || Integer.parseInt(hygieneGrade) > 2) {
            return false;
        }

        return true;
    }

    @Override
    public List<StuLeaveApply> getStuLeaveApplyList(Long studentId) {
        LambdaQueryWrapper<StuLeaveApply> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StuLeaveApply::getStudentId,studentId).orderByDesc(StuLeaveApply::getCreateTime);
        return this.stuLeaveApplyDao.selectList(wrapper);
    }

    @Override
    public List<Map<String, Object>> getStuLeaveApplyByClsTeacherId(Long clsTeacherId, String status) {
        LambdaQueryWrapper<BClass> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BClass::getStatus,"1").eq(BClass::getClassTeacherId,clsTeacherId);
        List<BClass> bClassList = bClassDao.selectList(wrapper);
        List<Map<String, Object>> list = new ArrayList<>();
        List<StuLeaveApply> applyList = new ArrayList<>();

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

        if(!bClassList.isEmpty()){
            for(BClass cls : bClassList){
                Map<String, Object> map = new HashMap<>();
                applyList = stuLeaveApplyDao.stuLeaveApply(clsTeacherId, status, cls.getId());

                if(!applyList.isEmpty()){
                    for (StuLeaveApply stuLeaveApply : applyList) {
                        if (stuLeaveApply.getStatus().equals("0")){
                            try {
                                //获取请假申请结束时间
                                Date parse = simpleDateFormat.parse(stuLeaveApply.getEndDate());

                                Calendar calendar = Calendar.getInstance();
                                calendar.set(Calendar.HOUR_OF_DAY, 0);
                                calendar.set(Calendar.MINUTE, 0);
                                calendar.set(Calendar.SECOND, 0);
                                calendar.set(Calendar.MILLISECOND, 0);

                                //系统当前时间
                                Date dateWithoutTime = calendar.getTime();
                                //比对请假是否过期
                                System.out.println(parse.compareTo(dateWithoutTime));
                                if(parse.compareTo(dateWithoutTime) < 0){
                                    stuLeaveApplyDao.updatePastDueLeave(cls.getId(),stuLeaveApply.getStudentId());
                                }

                            } catch (ParseException e) {
                                throw new RuntimeException(e);
                            }
                        }

                    }
                }

                System.out.println(applyList);
                applyList = stuLeaveApplyDao.stuLeaveApply(clsTeacherId, status, cls.getId());

                map.put("className",cls.getClassName());
                map.put("leaveApplyData",applyList);
                list.add(map);

            }
        }


        return list;
    }

    @Override
    public int updateStuLeaveApplyStatus(StuLeaveApply apply) {
        StuLeaveApply stuLeaveApply = stuLeaveApplyDao.selectById(apply.getId());
        
        if (Objects.isNull(stuLeaveApply)) {
            return -3;
        }

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        //系统当前时间
        Date today = calendar.getTime();

        Date leaveStartDate = null;
        try {
            leaveStartDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(stuLeaveApply.getEndDate() + " 00:00:00");
            if(leaveStartDate.compareTo(today) < 0){
                stuLeaveApply.setModifyTime(today);
                stuLeaveApply.setStatus("2");
                stuLeaveApply.setRejectReason("当前审批时间晚于请假日期，系统自动驳回");
                stuLeaveApplyDao.updateById(stuLeaveApply);
                return -2;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }

        BStudent student = bStudentDao.selectById(stuLeaveApply.getStudentId());
        if(apply.getStatus().equals("1")){
            // 审批通过
            try {
                // 插入考勤数据
                addStudentNewLeave(student, stuLeaveApply);
            } catch (ParseException e) {
                log.error(e.getMessage());
            }
        }

        String successInfo = "";

        if(apply.getStatus().equals("1")){
            successInfo = "通过";
            // 生成离校凭证
            LeavingSchoolCertificate certificate = new LeavingSchoolCertificate();
            certificate.setStudentId(stuLeaveApply.getStudentId());
            Date date = new Date();
            try {
                date = org.apache.commons.lang3.time.DateUtils.parseDate(stuLeaveApply.getStartDate(), "yyyy-MM-dd HH:mm:ss");
            } catch (ParseException e) {
                e.printStackTrace();
            }
            certificate.setLeaveDate(date);
            schoolCertificateDao.insert(certificate);
            
            // 发送消息修改门禁规则
             Map<String, Object> map = new HashMap<>();
             map.put("reportAfterSchoolTime", null);
             map.put("leaveEndTime", stuLeaveApply.getEndDate());
             map.put("studentId", String.valueOf(student.getId()));
             map.put("studentName", student.getStudentName());
             map.put("leaveStartTime", stuLeaveApply.getStartDate());
             Map<String, Object> objectMap = BeanUtil.beanToMap(student);
             map.put("studentInfo", JSON.toJSONString(objectMap));
             taskExecutor.execute(() -> {
                 leaveMessageSender.sendMqMessage(JSON.toJSONString(map), null);
             });
        }

        if(apply.getStatus().equals("2")){
            successInfo = "拒绝";
        }

        // 发送微信推送通知
        Map<String, Object> weatherDataMap = weatherDataCreator.createResultWeatherDataMap(student.getStudentName(), successInfo,
                student.getStudentName(),DateUtil.formatDateTime(stuLeaveApply.getCreateTime()));
        try {

            JSONObject jsonObject = null;

            if(null != student.getWxOpenId()  && StringUtils.hasText(student.getWxOpenId())){
                jsonObject = wxUtil.sendInfo(student.getWxOpenId(), leaveResult_temp_id
                        , weatherDataMap,"");
            }

            if(null != student.getParentWxOpenId()  && StringUtils.hasText(student.getParentWxOpenId())){
                jsonObject = wxUtil.sendInfo(student.getParentWxOpenId(), leaveResult_temp_id
                        , weatherDataMap,"");
            }

        } catch (Exception e) {
            System.out.println(e);;
        }

        stuLeaveApply.setModifyTime(new Date());
        stuLeaveApply.setStatus(apply.getStatus());
        stuLeaveApply.setRejectReason(apply.getRejectReason());
        return stuLeaveApplyDao.updateById(stuLeaveApply);
    }
    
    private void addStudentNewLeave(BStudent student, StuLeaveApply stuLeaveApply) throws ParseException {
        
        // 添加申请表中的数据
        SdLeave sdLeave = new SdLeave();
        sdLeave.setClassId(student.getClassId());
        sdLeave.setClassName(student.getClassName());
        sdLeave.setStatus("3");
        sdLeave.setStudentNo(student.getStudentNo());
        sdLeave.setStudentName(student.getStudentName());
        sdLeave.setStartDate(stuLeaveApply.getStartDate());
        sdLeave.setEndDate(stuLeaveApply.getEndDate());
        sdLeave.setStudentPhone(student.getPhone());
        sdLeave.setLeaveReason(stuLeaveApply.getLeaveReason());
        sdLeave.setLeaveType(stuLeaveApply.getLeaveType());
        sdLeaveDao.insert(sdLeave);
        
        StudentDept studentDept = bStudentDao.getStudentDept(student.getStudentNo());
        // 审批通过请假
        // 1.根据请假开始时间和结束时间拆分出几天
        // 判断请假开始时间和结束时间是不是同一天
        if (isSameDay(stuLeaveApply.getStartDate(), stuLeaveApply.getEndDate())) {
            Date startTime = DateUtil.parse(stuLeaveApply.getStartDate(), "yyyy-MM-dd HH:mm:ss", Locale.CHINA);
            Date enTime = DateUtil.parse(stuLeaveApply.getEndDate(), "yyyy-MM-dd HH:mm:ss", Locale.CHINA);
            // 同一天 判断是否需要插入周末考勤 请假结束时间在考勤点之前则不需要插入周末考勤
            DateTime clockTime = getWeekendClockTime(studentDept, stuLeaveApply.getStartDate());
            if (Objects.nonNull(clockTime)) {
                if (clockTime.isAfter(startTime) && clockTime.isBefore(enTime)) {
                    // 插入周末考勤
                    if (needAddWeekendData(student.getStudentNo(), stuLeaveApply.getStartDate())) {
                        SdWeekendAttence weekendAttence = createWeekendAttence(student, stuLeaveApply.getStartDate());
                        sdWeekendAttenceDao.insert(weekendAttence);
                    }
                }
            }
            DateTime dormitoryClockTime = getNowDormitoryClockTime(stuLeaveApply.getEndDate());
            // 判断是否需要插入宿舍考勤
            if (dormitoryClockTime.isAfter(startTime) && dormitoryClockTime.isBefore(enTime)) {
                // 插入宿舍考勤
                SdAttence sdAttence = createSdAttence(student, stuLeaveApply.getStartDate());
                sdAttenceService.insert(sdAttence);
            }
            return;
        }
        // 请假时间不在同一天
        List<String> allDate = new ArrayList<>();
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 定义两个日期时间
        LocalDateTime startDateTime = LocalDateTime.parse(stuLeaveApply.getStartDate(), formatter);
        LocalDateTime endDateTime = LocalDateTime.parse(stuLeaveApply.getEndDate(), formatter);
    
        // 输出中间的日期（只考虑日期部分）
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDateTime currentDateTime = startDateTime.toLocalDate().atStartOfDay();
    
        while (currentDateTime.toLocalDate().isBefore(endDateTime.toLocalDate()) ||
                currentDateTime.toLocalDate().isEqual(endDateTime.toLocalDate())) {
            System.out.println(currentDateTime.format(formatter));
            allDate.add(currentDateTime.format(formatter));
            currentDateTime = currentDateTime.plusDays(1);
        }
        
        // 移除掉开始时间和结束时间，这两个时间要另外判断  中间的日期则直接插入到考勤表中
        allDate.remove(0);
        allDate.remove(allDate.size() - 1);
        // 处理开始时间和结束时间的时间点情况
        // 判断请假开始时间 是否需要插入周末考勤 是否需要插入宿舍考勤 请假开始时间在考勤点时间之前则需要插入宿舍考勤
        if (todayNeedInsertWeekendLeaveClock(studentDept, stuLeaveApply.getStartDate(), 2)) {
            // 需要插入周末考勤
            if (needAddWeekendData(student.getStudentNo(), stuLeaveApply.getStartDate())) {
                SdWeekendAttence weekendAttence = createWeekendAttence(student, stuLeaveApply.getStartDate());
                sdWeekendAttenceDao.insert(weekendAttence);
            }
        }
        if (todayNeedInsertDormitoryLeaveClock(studentDept, stuLeaveApply.getStartDate(), 2)) {
            // 需要插入宿舍考勤
            SdAttence sdAttence = createSdAttence(student, stuLeaveApply.getStartDate());
            sdAttenceService.insert(sdAttence);
        }
    
        // 处理请假结束时间节点信息 如果结束时间在考勤节点之前，则不需要插入考勤信息，如果在考勤节点之后则需要插入考勤信息
        if (todayNeedInsertWeekendLeaveClock(studentDept, stuLeaveApply.getEndDate(), 1)) {
            // 需要插入周末考勤
            if (needAddWeekendData(student.getStudentNo(), stuLeaveApply.getEndDate())) {
    
                SdWeekendAttence weekendAttence = createWeekendAttence(student, stuLeaveApply.getEndDate());
                sdWeekendAttenceDao.insert(weekendAttence);
            }
        }
        if (todayNeedInsertDormitoryLeaveClock(studentDept, stuLeaveApply.getEndDate(), 1)) {
            // 需要插入宿舍考勤
            SdAttence sdAttence = createSdAttence(student, stuLeaveApply.getEndDate());
            sdAttenceService.insert(sdAttence);
        }
        
        if (CollectionUtil.isEmpty(allDate)) {
            return;
        }
        
        // 中间时间日期则直接插入到考勤表中
        for (String dateTime : allDate) {
            //向考勤表添加考勤信息
            SdAttence sdAttence = createSdAttence(student, dateTime);
            sdAttenceService.insert(sdAttence);
            
            // 向周末考勤表中添加请假考勤信息
            if (needAddWeekendData(student.getStudentNo(), dateTime)) {
                SdWeekendAttence sdWeekendAttence = createWeekendAttence(student, dateTime);
                sdWeekendAttenceDao.insert(sdWeekendAttence);
            }
        }
    }
    
    // 为true时可以插入数据，为false则不可以插入数据
    private boolean needAddWeekendData(String studentNo, String accessDate) {
        // 查询周末考勤表中是否有数据
        List<SdWeekendAttence> sdWeekendAttences = sdWeekendAttenceDao.getAttenceByDateAndStudentNo(accessDate, studentNo);
        if (CollectionUtil.isEmpty(sdWeekendAttences)) {
            return true;
        }
        return false;
    }
    
    private SdAttence createSdAttence(BStudent student, String dateTime) {
        SdAttence sdAttence = new SdAttence();
        sdAttence.setAccessDate(new Date());
        sdAttence.setStudentNo(student.getStudentNo());
        sdAttence.setAttenceStatus(CommonConstant.ATTENDANCE_LEAVE);
        sdAttence.setBdormitoryId(student.getBdormitoryId());
        sdAttence.setBuildingNo(student.getBuildingNo());
        sdAttence.setStorey(student.getStorey());
        sdAttence.setDormitoryNo(student.getDormitoryNo());
        sdAttence.setFlag("3");
        sdAttence.setCreateTime(new Date());
        sdAttence.setModifyTime(new Date());
        //2021-11-1需求变更（支持一次性请假多天）
        sdAttence.setAccessDate(DateUtil.parse(dateTime, "yyyy-MM-dd HH:mm:ss", Locale.CHINA));
        return sdAttence;
    }
    
    private SdWeekendAttence createWeekendAttence(BStudent student, String dateTime) {
        // 向周末考勤表中添加考勤信息
        SdWeekendAttence sdWeekendAttence = new SdWeekendAttence();
        sdWeekendAttence.setAccessDate(new Date());
        sdWeekendAttence.setStudentNo(student.getStudentNo());
        sdWeekendAttence.setAttenceStatus(CommonConstant.ATTENDANCE_LEAVE);
        sdWeekendAttence.setBdormitoryId(student.getBdormitoryId());
        sdWeekendAttence.setBuildingNo(student.getBuildingNo());
        sdWeekendAttence.setStorey(student.getStorey());
        sdWeekendAttence.setDormitoryNo(student.getDormitoryNo());
        sdWeekendAttence.setFlag("3");
        sdWeekendAttence.setCreateTime(new Date());
        sdWeekendAttence.setModifyTime(new Date());
        sdWeekendAttence.setAccessDate(DateUtil.parse(dateTime, "yyyy-MM-dd HH:mm:ss", Locale.CHINA));
        return sdWeekendAttence;
    }
    
    private boolean isSameDay(String startDate, String endDate) throws ParseException {
    
//        String startTime = DateUtils.formatDate(startD, "yyyy-MM-dd");
    
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 将字符串转换为 LocalDateTime 对象
        LocalDateTime localDateTime = LocalDateTime.parse(startDate, inputFormatter);
        // 定义输出格式
        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    
        // 格式化为年月日的字符串
        String startTime = localDateTime.format(outputFormatter);
        LocalDateTime localEndDateTime = LocalDateTime.parse(endDate, inputFormatter);
        String endTime = localEndDateTime.format(outputFormatter);
//        String endTime = DateUtils.formatDate(endD, "yyyy-MM-dd");
        
        if (startTime.equals(endTime)) {
            return true;
        }
        return false;
    }
    
    // 获取打卡截止日期，如果不在周末考勤时间，则返回空
    private DateTime getWeekendClockTime(StudentDept studentDept, String accessDate) {
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 将字符串转换为 LocalDateTime 对象
        LocalDateTime localDateTime = LocalDateTime.parse(accessDate, inputFormatter);
        // 定义输出格式
        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    
        // 格式化为年月日的字符串
        String nowDate = localDateTime.format(outputFormatter);
  
        //根据部门Id和请假日期判断当前学生请假是否在返校日期  在返校日期则需要考虑是否需要添加周末考勤
        HolidayConfig holidayConfig = holidayConfigDao.getHolidayByDeptIdAndDate(String.valueOf(studentDept.getDeptPid()), nowDate);
        // 如果为空 不在返校日期
        if(Objects.isNull(holidayConfig)) {
            return null;
        }
        
        // 在返校日期  判断该时间是否在周末配置的打卡截止时间之前  之前则不需要  之后则需要添加周末考勤数据
        LambdaQueryWrapper<SysConfig> sdWeekendRulesWrapper = new LambdaQueryWrapper<>();
        sdWeekendRulesWrapper.eq(SysConfig::getParamKey,"dormitory.weekend.rules");
        SysConfig sdWeekendRules = sysConfigDao.selectOne(sdWeekendRulesWrapper);
        String[] attendanceWeekendRange = sdWeekendRules.getParamValue().split("-");
        String weekendEndTime = attendanceWeekendRange[1];
    
        // 打卡截止日期
        DateTime clockTime = DateUtil.parse(nowDate + " " + weekendEndTime+":00", "yyyy-MM-dd HH:mm:ss", Locale.CHINA);
     
        return clockTime;
    }
    
    private DateTime getNowDormitoryClockTime(String accessDate) {
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 将字符串转换为 LocalDateTime 对象
        LocalDateTime localDateTime = LocalDateTime.parse(accessDate, inputFormatter);
        // 定义输出格式
        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String nowDate = localDateTime.format(outputFormatter);
    
        // 在返校日期  判断该时间是否在周末配置的打卡截止时间之前  之前则不需要  之后则需要添加周末考勤数据
        LambdaQueryWrapper<SysConfig> sdDormitoryRulesWrapper = new LambdaQueryWrapper<>();
        sdDormitoryRulesWrapper.eq(SysConfig::getParamKey,"attendance.dormitory.rules");
        SysConfig sdDormitoyRules = sysConfigDao.selectOne(sdDormitoryRulesWrapper);
        String[] attendanceDormitoryRange = sdDormitoyRules.getParamValue().split("-");
        String  dormitoryEndTime= attendanceDormitoryRange[1];
    
        // 打卡截止日期
        DateTime clockTime = DateUtil.parse(nowDate + " " + dormitoryEndTime+":00", "yyyy-MM-dd HH:mm:ss", Locale.CHINA);
        return clockTime;
    }
    
    /**
     * 判断学生请假当天是否需要周末考勤
     * @author alex
     * @date 2024/10/24 11:14
     * @return
     */
    private boolean todayNeedInsertWeekendLeaveClock(StudentDept studentDept, String endDate, Integer type) {
        Date endTime = DateUtil.parse(endDate, "yyyy-MM-dd HH:mm:ss", Locale.CHINA);
    
        DateTime clockTime = getWeekendClockTime(studentDept, endDate);
        
        if (Objects.isNull(clockTime)) {
            return false;
        }
    
        // 请假日期
//        Date accessTime = DateUtils.parseDate(accessDate);
        // 打卡截止时间在请假时间之后，不需要插入周末考勤数据   如果是多天请假，请假结束时间在考勤时间点之前则不需要插入请假考勤数据
        if (type == 1 && clockTime.isAfter(endTime)) {
                return false;
        }
        
        // type 为2则为多天请假 请假开始时间点如果在考勤点之前，则需要插入请假考勤数据
        if (type == 2 && clockTime.isAfter(endTime)) {
            return true;
        }
        return true;
    }
    
    private boolean todayNeedInsertDormitoryLeaveClock(StudentDept studentDept, String accessDate, Integer type) {
        Date date = DateUtil.parse(accessDate, "yyyy-MM-dd HH:mm:ss", Locale.CHINA);
    
        DateTime clockTime = getNowDormitoryClockTime(accessDate);
        // 请假日期
//        Date accessTime = DateUtils.parseDate(accessDate);
        // 打卡截止时间在请假时间之后，不需要插入周末考勤数据
        // 打卡截止时间在请假时间之后，不需要插入周末考勤数据   如果是多天请假，请假结束时间在考勤时间点之前则不需要插入请假考勤数据
        if (type == 1 && clockTime.isAfter(date)) {
            return false;
        }
        // type 为2则为多天请假 请假开始时间点如果在考勤点之前，则需要插入请假考勤数据
        if (type == 2 && clockTime.isAfter(date)) {
            return true;
        }
        
        if (type == 2 && clockTime.isBefore(date)) {
            return false;
        }
        
        return true;
    }
    
    @Override
    public int revokeStuLeaveApply(Long stuLeaveApplyId) {
        StuLeaveApply stuLeaveApply = stuLeaveApplyDao.selectById(stuLeaveApplyId);
        if(stuLeaveApplyId.equals("0")){
            stuLeaveApply.setStatus("3");
            stuLeaveApply.setModifyTime(new Date());
            return stuLeaveApplyDao.updateById(stuLeaveApply);
        }else {
            return -1;
        }
    }



    /**
     * 查询请假学生相关信息
     * @param studentId
     * @return
     */
    @Override
    public List<StuLeaveApply> studentLeaveCorrelationInfo(Long studentId) {

        return stuLeaveApplyDao.studentLeaveCorrelationInfo(studentId);
    }
    
    @Override
    public int studentCancelLeaveApply(StuLeaveApply leaveApply) {
        // 更改请假申请单的状态
        StuLeaveApply stuLeaveApply = stuLeaveApplyDao.selectById(leaveApply.getId());
        LambdaUpdateWrapper<StuLeaveApply> updateWrapper = new LambdaUpdateWrapper();
        if (stuLeaveApply.getStatus().equals("0")) {
            updateWrapper.set(StuLeaveApply::getStatus, "4").eq(StuLeaveApply::getId, stuLeaveApply.getId());
        }
        
        if (stuLeaveApply.getStatus().equals("1")) {
            updateWrapper.set(StuLeaveApply::getStatus, "5").eq(StuLeaveApply::getId, stuLeaveApply.getId());
        }
        int update = stuLeaveApplyDao.update(stuLeaveApply, updateWrapper);
        return update;
    }
    
    @Override
    @Transactional
    public void  cancelStuLeaveApply(StuLeaveApply stuLeaveApply) {
        // 更改请假申请单的状态
        StuLeaveApply leaveApply = stuLeaveApplyDao.selectById(stuLeaveApply.getId());
        
        // 查询出学生信息
        BStudent bStudent = bStudentDao.selectById(leaveApply.getStudentId());
    
        LambdaUpdateWrapper<StuLeaveApply> updateWrapper = new LambdaUpdateWrapper();
        updateWrapper.set(StuLeaveApply::getStatus, "4").eq(StuLeaveApply::getId, leaveApply.getId());
    
        int update = stuLeaveApplyDao.update(leaveApply, updateWrapper);
    
//        String nowDate = DateUtil.formatDate(new Date());
        String nowDate = com.alibaba.excel.util.DateUtils.format(new Date());
        
        if (update > 0) {
            // 撤销学生请假申请  需要去除掉当前时间到请假结束时间范围内 考勤表中插入的考勤数据
            stuLeaveApply.setStartDate(nowDate);
            String endDate = leaveApply.getEndDate();
            // 先去出掉宿舍考勤中的请假数据
            sdAttenceService.deleteDormitoryLeaveAttenceInfo(String.valueOf(bStudent.getStudentNo()), nowDate, endDate);
            
            // 去除周末考勤表中的请假数据
            sdWeekendAttenceDao.deleteWeekendLeaveAttenceInfo(String.valueOf(bStudent.getStudentNo()), nowDate, endDate);
            
            // 将门禁中学生的原有规则修改回来
            try {
                Map<String, Object> map = new HashMap<>();
                map.put("reportAfterSchoolTime", nowDate);
                map.put("leaveEndTime", leaveApply.getEndDate());
                map.put("studentId", String.valueOf(bStudent.getId()));
                map.put("studentName", bStudent.getStudentName());
                map.put("leaveStartTime", stuLeaveApply.getStartDate());
                Map<String, Object> objectMap = BeanUtil.beanToMap(bStudent);
                map.put("studentInfo", JSON.toJSONString(objectMap));
                taskExecutor.execute(() -> {
                    leaveMessageSender.sendMqMessage(JSON.toJSONString(map), null);
                });
            }catch (Exception e) {
                log.info("发送撤销请假消息失败! 学生姓名: {}。 学号：{}" , bStudent.getStudentName() , bStudent.getStudentNo());
            }
        }
    }
}
